#ifndef     __RT_WORK_H
#define     __RT_WORK_H

#include <memory>
#include "../app.h"
#include <type_traits>
#include "./task2.h"
#include "./future2.h"
#include "../utils/log.h"

namespace rt {

void post_to_default(HandlerPtr&& ptr);

template <typename F>
inline void run_on_default(F&& f) {
    post_to_default( make_handler(std::move(f)) );
}

void init();
void exit();

inline Task2<> delay(int ms) {
    CompletabledFuture2<> future;
    run_on_delay(ms, [weak = future.weak()] () mutable {
        auto p = weak.lock();
        if (p) {
            p->complete();
        }
    });
    co_await future;
}

template <typename F>
Task2< std::invoke_result_t<F> > run_async(F&& f) {
    using R = std::invoke_result_t<F>;
    CompletabledFuture2<R> future;
    run_on_default([f1 = std::move(f), weak = future.weak()] () mutable {
        Result2<R> result;
        try {
            if constexpr (std::is_same_v<R, void>) {
                f1();
                result.set_value();
            } else {
                result.set_value( f1() );
            }
        } catch (...) {
            result.set_err(std::current_exception());
        }
        run_on_ui([weak, r = std::move(result)] () mutable {
            auto p = weak.lock();
            if (p) {
                if constexpr (std::is_same_v<R, void>) {
                    p->complete();
                } else {
                    p->complete( std::move(r) );
                }
            }
        });
    });
    if constexpr ( std::is_same_v<R, void> ) {
        co_await future;
    } else {
        R value = co_await future;
        co_return value;
    }
}

}

#endif
